﻿// DlgExport.cpp: 实现文件
//

#include "pch.h"
#include "PE_Studio.h"
#include "PE_StudioDlg.h"
#include "afxdialogex.h"
#include "DlgExport.h"


// DlgExport 对话框

IMPLEMENT_DYNAMIC(DlgExport, CDialogEx)

DlgExport::DlgExport(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DLG_EXPORT, pParent)
{

}

void DlgExport::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST_EXPORT_FUNCTIONS, m_ListExport);
}

BEGIN_MESSAGE_MAP(DlgExport, CDialogEx)
	ON_BN_CLICKED(IDOK, &DlgExport::OnBnClickedOk)
	ON_BN_CLICKED(IDCANCEL, &DlgExport::OnBnClickedCancel)
END_MESSAGE_MAP()


// DlgExport 消息处理程序

BOOL DlgExport::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	
    // 初始化 ListCtrl 顶栏列数据
	m_ListExport.SetListCtrl(TRUE, TRUE, FALSE, FALSE, TRUE);		// 禁止排序
	m_ListExport.EnableContextMenu(TRUE);
	m_ListExport.InsertColumn(0, TEXT("NO."), LVCFMT_CENTER, 50);
	m_ListExport.InsertColumn(1, TEXT("NO."), LVCFMT_CENTER, 50);
	m_ListExport.InsertColumn(2, TEXT("Ordinal"), LVCFMT_CENTER, 100);
	m_ListExport.InsertColumn(3, TEXT("RVA"), LVCFMT_CENTER, 100);
	m_ListExport.InsertColumn(4, TEXT("Offset"), LVCFMT_CENTER, 100);
	m_ListExport.InsertColumn(5, TEXT("FunctionName"), LVCFMT_CENTER, 200);
	m_ListExport.DeleteColumn(0);    

    // 初始化输出表数据
	InitExportTable();

	// ToolTip 提示
	m_ToolTip.Create(this);
	m_ToolTip.AddTool(GetDlgItem(IDC_EDIT_EXP_ADDRFUNC), szAddressOfNames);
	m_ToolTip.AddTool(GetDlgItem(IDC_EDIT_EXP_ADDRNAME), szAddressOfNames);
	m_ToolTip.AddTool(GetDlgItem(IDC_EDIT_EXP_ADDRORD), szAddressOfNames);

    // 设定显示宽度，超长内容自动换行
    m_ToolTip.SetMaxTipWidth(500);
 //   // 设定提示控件的延迟时间，默认500毫秒
 //   // m_ToolTip.SetDelayTime(500);
 //   // 鼠标保持指向，提示显示多久，毫秒，默认一起提示
 //   m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 10000);
 //   // 鼠标指向多久后显示提示，默认500毫秒
 //   m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
 //   // 从一个控件移动到另一个控件，显示提示信息的延迟，毫秒
 //   m_ToolTip.SetDelayTime(TTDT_RESHOW, 500);
 //   // 文字颜色
 //   m_ToolTip.SetTipTextColor(RGB(255, 0, 0));
	//m_ToolTip.SetTipBkColor(RGB(200, 200, 200));
	m_ToolTip.Activate(TRUE);
    
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void DlgExport::InitExportTable()
{
	m_ListExport.DeleteAllItems();

	//获取导入函数表在内存文件中的偏移
	CPEStudioDlg* pHwndParent = (CPEStudioDlg*)(AfxGetApp()->GetMainWnd());	// 父窗口句柄
	PIMAGE_EXPORT_DIRECTORY pExportDir = pHwndParent->m_pPE->m_pExportDirectory;
	
	CString szTemp = TEXT("");

	// Characteristics
	szTemp.Format(TEXT("%08X"), pExportDir->Characteristics);
	SetDlgItemText(IDC_EDIT_EXP_CHAR, szTemp);
    
    // TimeDateStamp
	szTemp.Format(TEXT("%08X"), pExportDir->TimeDateStamp);
	SetDlgItemText(IDC_EDIT_EXP_TIMESTAMP, szTemp);
    
    // MajorVersion
	szTemp.Format(TEXT("%04X"), pExportDir->MajorVersion);
	SetDlgItemText(IDC_EDIT_EXP_MAJOR, szTemp);
    
    // MinorVersion
	szTemp.Format(TEXT("%04X"), pExportDir->MinorVersion);
	SetDlgItemText(IDC_EDIT_EXP_MINOR, szTemp);
    
    // Name
	BYTE* pName = (BYTE*)pHwndParent->m_pPE->RVAtoFOA(pExportDir->Name, (DWORD)pHwndParent->m_pPE->m_pImageBase);
	SetDlgItemText(IDC_EDIT_EXP_NNAME, (CString)pName);

	// Base
	szTemp.Format(TEXT("%08X"), pExportDir->Base);
	SetDlgItemText(IDC_EDIT_EXP_NBASE, szTemp);
    
	// NumberOfFunctions
	szTemp.Format(TEXT("%08X"), pExportDir->NumberOfFunctions);
	SetDlgItemText(IDC_EDIT_EXP_NUMBERFUNC, szTemp);
    
    // NumberOfNames
	szTemp.Format(TEXT("%08X"), pExportDir->NumberOfNames);
	SetDlgItemText(IDC_EDIT_EXP_NUMBERNAME, szTemp);
    
    // AddressOfFunctions
	szTemp.Format(TEXT("%08X"), pExportDir->AddressOfFunctions);
	SetDlgItemText(IDC_EDIT_EXP_ADDRFUNC, szTemp);
    
    // AddressOfNames
	szTemp.Format(TEXT("%08X"), pExportDir->AddressOfNames);
	SetDlgItemText(IDC_EDIT_EXP_ADDRNAME, szTemp);
    
    // AddressOfNameOrdinals
	szTemp.Format(TEXT("%08X"), pExportDir->AddressOfNameOrdinals);
	SetDlgItemText(IDC_EDIT_EXP_ADDRORD, szTemp);   

    // 初始化导出函数表
    PDWORD pAddressOfFunctions = (PDWORD)(pHwndParent->m_pPE->RVAtoFOA(pExportDir->AddressOfFunctions, (DWORD)pHwndParent->m_pPE->m_pImageBase));
    PDWORD pAddressOfNames = (PDWORD)(pHwndParent->m_pPE->RVAtoFOA(pExportDir->AddressOfNames, (DWORD)pHwndParent->m_pPE->m_pImageBase));
    DWORD nBase = pExportDir->Base;
	BYTE* pFunctionName = NULL;
	for (int i = 0; i < pExportDir->NumberOfFunctions; i++)
    {
		//if (NULL == pAddressOfFunctions[i])
		//{
		//	continue;
		//}
		
		// NO.
		szTemp.Format(TEXT("%d"), i + 1);
		m_ListExport.InsertItem(i, szTemp);
        
        // Ordinal
		szTemp.Format(TEXT("%04X"), nBase + (DWORD)i);
        m_ListExport.SetItemText(i, 1, szTemp);
        
        // RVA
        szTemp.Format(TEXT("%08X"), pAddressOfFunctions[i]);
        m_ListExport.SetItemText(i, 2, szTemp);
		
        // Offset
		szTemp.Format(TEXT("%08X"), pHwndParent->m_pPE->RVAtoFOA(pAddressOfFunctions[i]));
		m_ListExport.SetItemText(i, 3, szTemp);
        
        // FunctionName
		m_ListExport.SetItemText(i, 4, TEXT("-"));
    }

    // 初始化导出函数名表
	PWORD pAddressOfNameOrdinals = (PWORD)(pHwndParent->m_pPE->RVAtoFOA(pExportDir->AddressOfNameOrdinals, (DWORD)pHwndParent->m_pPE->m_pImageBase));
	int nNumberOfNames = (int)(pExportDir->NumberOfNames);
	int nSerialNum = 0;
	int nTemp = 0;
    for (int nNumber = 0; nNumber < nNumberOfNames; nNumber++)
    {
		nSerialNum = (int)pAddressOfNameOrdinals[nNumber];
		pFunctionName = (BYTE*)(pHwndParent->m_pPE->RVAtoFOA(pAddressOfNames[nNumber], (DWORD)pHwndParent->m_pPE->m_pImageBase));
		m_ListExport.SetItemText(nSerialNum, 4, (CString)pFunctionName);        
    }

	// 去除空白导出函数，即RVA为“00000000”的对应item
    int nCol = 2;    // 搜索RVA列
    CString SearchThisItemText = _T("00000000");
    for (int i = 0; i < m_ListExport.GetItemCount(); ++i)
    {
        CString szText = m_ListExport.GetItemText(i, nCol);
        if (szText == SearchThisItemText)
        {            
			m_ListExport.DeleteItem(i);
			i--;
        }
    }
}

void DlgExport::OnBnClickedOk()
{
	CDialogEx::OnOK();
}

void DlgExport::OnBnClickedCancel()
{
	CDialogEx::OnCancel();
}

BOOL DlgExport::PreTranslateMessage(MSG* pMsg)
{
	if (NULL != m_ToolTip)
		m_ToolTip.RelayEvent(pMsg);
	return CDialogEx::PreTranslateMessage(pMsg);
}
